package mx.unam.fciencias.ppc.beansboard.comm;

import java.io.*;
import java.net.*;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Calendar;

/**
 *
 * @author lander
 */
public final class CollabServiceServerMain implements Runnable {

    private ServerSocket socket;
    private String exitMessage;
    private LinkedList <CollabServiceServerThread> servers;
    private File path;
    private FileOutputStream fos;
    private PrintWriter logfile;
    private String logname;
    private boolean running;
    
    /**
     * Creates a new <code>CollabServiceServer</code>
     * @param port Port to listen
     * @param path Path of the project to work on
     * @throws java.io.IOException
     */
    public CollabServiceServerMain(int port, File path) throws IOException {
        socket = new ServerSocket(port);
        exitMessage = null;
        servers = new LinkedList <CollabServiceServerThread>();
        this.path = path;
        logname = "BeansBoard.log";
        fos = new FileOutputStream(path.getAbsolutePath()+"/"+logname, true);
        logfile = new PrintWriter(fos, true);
        running = false;
    }

    public String getErrorMessage() {
        return exitMessage;
    }

    /**
     * Returns the working project path
     * @return Path of the working project
     */
    protected File getPath(){
        return path;
    }
    
    /**
     * Appends a message into de logfile
     * @param message Message to be append
     */
    protected void log(String message){
        logfile.println(message);
    }
    
    /**
     * Removes a <code>CollabServiceServerThread</code> from the servers list.
     * @param leaving The <code>CollabServiceServerThread</code> leaving
     */
    protected void logout(CollabServiceServerThread leaving){
            servers.remove(leaving);
    }
    
    public void run() {
        log("New session started on: "+Calendar.getInstance().getTime());
        running = true;
        while (running) {
            try {
                Socket s = socket.accept();
                CollabServiceServerThread serverThread = new CollabServiceServerThread(s, this);
                Thread t = new Thread(serverThread);
                t.start();
                servers.add(serverThread);
            } catch (Exception e) {
                exitMessage = "Error " + e.getMessage();
            }
        }
    }

    /**
     * Returns de number of the currently connected users to this server.
     * @return number of connected users.
     */
    public int usersOnline(){
            return servers.size();
    }
    
    /**
     * Broadcasts a message to all the clients except the one sending the message
     * @param message Message to broadcast
     * @param t Client sending the message
     */
    protected final void broadcast(String message, CollabServiceServerThread t){
        ListIterator<CollabServiceServerThread> it = servers.listIterator();
        while(it.hasNext()){
            CollabServiceServerThread s = it.next();
            if(s != t){
                s.sendMessage(message);
            }
        }
    }
    
    /**
     * Prints the usage of the program into the error output
     */
    private static void usage() {
        System.err.println("\n Usage: \n java -jar BeansBoard.jar <port> <path> \n Where: \n<port> is a valid TCP/IP port number" +
                "<path> is a valid path for the project");
    }

    public static void main(String[] args) {
        if (args.length != 2) {
            usage();
            System.exit(1);
        }
        try {
            int port = Integer.parseInt(args[0]);
            File f = new File(args[1]);
            if(!f.exists() || !f.isDirectory()){
                System.err.println("Invalid path");
                usage();
            }
            CollabServiceServerMain server = new CollabServiceServerMain(port, f);
            System.out.println("Press CTRL + C to stop the server");
            server.run();
        } catch (NumberFormatException nfe) {
            System.err.println("The specified argument is not a valid port number");
            usage();
            System.exit(2);
        } catch (IOException ioe) {
            System.err.println("Couldn't open socket: \n" + ioe.getMessage());
            System.exit(3);
        }

    }
}
